package com.heartunderblade.rpc.handler;

import com.heartunderblade.rpc.Registry.LocalRegistry;
import com.heartunderblade.rpc.RpcPojo.RpcRequest;
import com.heartunderblade.rpc.RpcPojo.RpcResponse;
import com.heartunderblade.rpc.protocol.ProtocolMessage;
import com.heartunderblade.rpc.protocol.ProtocolMessageStatusEnum;
import com.heartunderblade.rpc.protocol.ProtocolMessageTypeEnum;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;

import java.lang.reflect.Method;

public class TcpServerHandler extends SimpleChannelInboundHandler<ProtocolMessage> {
    /**
     * 重写TCP的handler，不用原来的HTTP的handler，对应解码后的ProtocolMessage对象
     * @param ctx
     * @param protocolMessage
     * @throws Exception
     */
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, ProtocolMessage protocolMessage) throws Exception {
        //处理请求
        RpcRequest rpcRequest = (RpcRequest) protocolMessage.getBody();
        ProtocolMessage.Header header = protocolMessage.getHeader();
        //构造返回结果对象
        RpcResponse rpcResponse = new RpcResponse();
        try {
            //利用反射得到结果
            //从本地拿到实现类
            Class<?> implClass  = LocalRegistry.get(rpcRequest.getServiceName());
            Method method = implClass .getMethod(rpcRequest.getMethodName(), rpcRequest.getArgsType());
            //反射写错了implClass.newInstance()，是实现类
            Object result  = method.invoke(implClass.newInstance() , rpcRequest.getArgs());
            rpcResponse.setData(result);
            rpcResponse.setDataType(method.getReturnType());
            rpcResponse.setMessage(" ok");
        } catch (Exception e) {
            e.printStackTrace();
            rpcResponse.setMessage(e.getMessage());
            rpcResponse.setException(e);
        }
        //设置类型响应请求，从ProtocolMessageTypeEnum获取
        header.setType((byte) ProtocolMessageTypeEnum.RESPONSE.getKey());
        //设置返回状态，从ProtocolMessageTypeEnum获取
        header.setStatus((byte) ProtocolMessageStatusEnum.OK.getValue());
        //设置响应协议
        ProtocolMessage<RpcResponse> rpcResponseProtocolMessage = new ProtocolMessage<>(header, rpcResponse);
        //直接发送，出站的时候会经过ProtocolMessageEncoderDecoder编码
        ctx.writeAndFlush(rpcResponseProtocolMessage);
    }
}
